using System;
using System.Collections.Generic;
using System.Configuration;
using Less.Core;
using Less.Core.Model;
using Less.Tools;


namespace Less.DAL
{
    /// <summary>
    /// An utility class to read and write configuration settings from / to a database
    /// </summary>
    internal class ConfigSettingsDAL : GenericDAL<ConfigSetting>
    {
        internal object ReadToken = new object();
        internal object WriteToken = new object();

        internal new string AllColumns
        {
            get
            {
                string name = ConfigurationManager.AppSettings["ConfigSettingsDAL.AllColumns"];
                if (name == null) name = " Id, Code, Culture, Value";
                return name;
            }
        }

        internal ConfigSettingsDAL(IDatabase database)
            : base(database)
        {

        }
        
        internal ConfigSettingsDAL():base (new Database(LessDatabaseUtils.LessConnectionStringName))
        {
            
        }

        /// <summary>
        /// Gets a ConfigSetting Record 
        /// </summary>
        /// <param name="code">The Role name</param>
        /// <returns>The ConfigSetting Record </returns>
        internal ConfigSetting SelectByCode(string code)
        {
            return base.SelectByFieldValue("Code", code);
        }

        /// <summary>
        /// Gets a Role Record 
        /// </summary>
        /// <param name="code">The Role name</param>
        /// <param name="culture"></param>
        /// <returns>The ConfigSetting Record </returns>
        internal ConfigSetting SelectByCodeCulture(string code, string culture)
        {
            ConfigSetting record = null;
            record = Database.Select<ConfigSetting>(
                       String.Format("SELECT {0} FROM {1} WHERE Code=@0 AND Culture=@1", AllColumns, TableName), code,
                       culture);
            if (record == null)
            {
                record = SelectByCode(code);
            }
            return record;
        }

        

        // OPTI: Use Update and Delete sentences

        internal new ConfigSetting Update(ConfigSetting record)
        {
            ConfigSetting recordDB = SelectById(record.Id);
            if (recordDB != null)
            {
                Database.Update(TableName, record);
            }
            else
            {
                throw new RecordNotFoundException(record.Id.ToString());
            }
            return record;
        }

        
        internal IEnumerable<ConfigSetting> SelectAllTranslations()
        {
            List<ConfigSetting> list = null;
            list = Database.SelectList<ConfigSetting>(
                        String.Format("SELECT DISTINCT Code FROM {0} Where Culture is not null and Culture<>'' ",
                                      TableName));
            return list;
        }

        internal IEnumerable<ConfigSetting> SelectTranslationsByCode(string code)
        {
            List<ConfigSetting> list = null;
            list = Database.SelectList<ConfigSetting>(
                       String.Format("SELECT {0} FROM {1} Where Code = @0 ", AllColumns, TableName), code);
            return list;
        }

        internal void Write(ConfigSetting record)
        {
            if (record.Id > 0)
            {
                Update(record);
            }
            else
            {
                Insert(record);
            }
        }

        #region Helpers for core Config class
        
        /// <summary>
        /// Helper to read values from database
        /// </summary>
        /// <param name="code">The key name</param>
        /// <param name="culture"></param>
        /// <returns>The readed value or null if not found</returns>
        internal object ReadValue(string code, string culture = "")
        {
            object value = null;
            ConfigSetting configSetting = null;
            lock ( ReadToken )
            {
                var tmp = string.Format("SELECT {0} FROM {1} WHERE Code=@0", AllColumns, TableName);
                configSetting = Database.Select<ConfigSetting>(tmp, code);
            }
            if ( configSetting != default(ConfigSetting) )
            {
                value = configSetting.Value;
            }
            return value;
        }

        /// <summary>
        /// Helper to write values to the database
        /// </summary>
        /// <param name="code">The key name</param>
        /// <param name="value"></param>
        /// <param name="culture"></param>
        internal void WriteValue(string code, object value, string culture = "")
        {
            lock ( WriteToken )
            {
                ConfigSetting record = SelectByCode(code);
                if ( record == null )
                {
                    record = new ConfigSetting { Code = code, Value = value.ToString(), Culture = culture };
                    Insert(record);
                }
                else
                {
                    record.Value = value.ToString();
                    Update(record);
                }
            }
        }
        #endregion
    }
}